package com.zhjw.config.db;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.PropertySource;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.util.CollectionUtils;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * Created by zhjw on 2023/3/6
 * <p>
 * 多数据源配置类
 * </p>
 *
 * @author zhjw
 * @date 2023/3/6
 */
@Slf4j
@Configuration
@PropertySource(value = "classpath:application.properties")
public class MultipleDataSourceConfig {

    /**
     * 读取properties配的数据源信息
     *
     * @return
     */
    @Bean("dataSourcePropertiesMap")
    @ConfigurationProperties(prefix = "spring.datasource")
    public Map<String, Properties> dataSourcePropertiesMap() {
        return new HashMap(8);
    }

    /**
     * 读取properties配的数据源信息，装配为Bean
     *
     * @param dataSourcePropertiesMap 读取properties配的数据源信息
     */
    @Bean("dataSourceBeanMap")
    public Map dataSourceBeanMap(@Qualifier("dataSourcePropertiesMap") Map<String, Properties> dataSourcePropertiesMap) throws Exception {
        Map dataSourceBeanMap = new HashMap(8);
        if (CollectionUtils.isEmpty(dataSourcePropertiesMap)) {
            return dataSourceBeanMap;
        }

        //Properties装配Bean
        for (String key : dataSourcePropertiesMap.keySet()) {
            Properties properties = dataSourcePropertiesMap.get(key);
            DruidDataSource druidDataSource = new DruidDataSource();
            DruidDataSourceFactory.config(druidDataSource,properties);
            dataSourceBeanMap.put(key, druidDataSource);
        }

        return dataSourceBeanMap;
    }

    /**
     * 动态数据源: 通过AOP在不同数据源之间动态切换
     *
     * @return 数据源
     */
    @Primary
    @Bean(name = "dynamicRoutingDataSource")
    public DataSource dynamicRoutingDataSource(@Qualifier("dataSourceBeanMap") Map dataSourceBeanMap) {
        //实现Spring的AbstractRoutingDataSource接口，设置当前线程使用的数据源
        DynamicRoutingDataSource dynamicRoutingDataSource = new DynamicRoutingDataSource();

        // 默认数据源:不指定使用数据源，则使用默认数据源
        if (dataSourceBeanMap.get(DataSourceContextHolderWrapper.DEFAULT_DS) == null) {
            throw new IllegalArgumentException("Multiple datasource must define default master datasource!");
        }
        dynamicRoutingDataSource.setDefaultTargetDataSource(dataSourceBeanMap.get(DataSourceContextHolderWrapper.DEFAULT_DS));

        // 配置多数据源
        dynamicRoutingDataSource.setTargetDataSources(dataSourceBeanMap);
        return dynamicRoutingDataSource;
    }


    /**
     * 配置@Transactional注解事务
     *
     * @return 平台事务管理器
     */
    @Bean
    public PlatformTransactionManager transactionManager(@Qualifier("dynamicRoutingDataSource")DataSource dynamicRoutingDataSource) {
        return new DataSourceTransactionManager(dynamicRoutingDataSource);
    }


}
